﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;

namespace DienLib.PopUp
{
    /// <summary>
    /// Callback Method to check timeout every 1sec. True will stop CountDown. False continue CountDown until Time-Out
    /// </summary>
    /// <param name="sender">CountDownForm</param>
    /// <param name="retobj">retobj will be pass to return value from showdialog() method. If noret then assign its null value</param>
    /// <returns>True will close countdownform, False will continue countdown until timed out</returns>
    public delegate bool StopCountDownCheck(object sender, out object retobj);
    //public delegate void DoNext(IntPtr hWnd);
    /// <summary>
    /// Will Check the TimeOutDelegate method every 1 sec or after period of time that you input.
    /// </summary>
    public partial class CountDownForm : Form
    {
        private int _TimeOutSec;
        private int _CountDownSec;
        private bool _IsCounting;
        private bool _IsPolling;
        private StopCountDownCheck _Method;
        private object _RetObj = null;
        //private bool _IsWindow;
        //private string _Process;
        // private string _Window;
        //private DoNext _DoNext;
        private string _MessageRTF;

        /*public CountDownForm(int sec, StopCountDownCheck method)
        {
            InitializeComponent();
            _TimeOutSec = sec;
            _Method = method;
            _IsWindow = false;
        }*/

        /// <summary>
        /// Message in RTF Format
        /// </summary>
        public string MessageRTF
        {
            set { richTextBox1.Rtf = value; }
        }

        public string Message
        {
            set { richTextBox1.Text = value; }
        }

        /// <summary>
        /// Generic Timeout Countdown Form : check Timeout Condition (return from Delegate method) every second
        /// </summary>
        /// <param name="sec">Time to start count down in second</param>
        /// <param name="method">Delegate Method return Bool Value fof TimeOut Condition, true : will time out, false : continue count down</param>
        /// <param name="title">Title for Count down Form</param>
        /// <param name="richtext">Richtext Box in Countdown Form, Run DienLib.Rtf2String for rtf to string code</param>
        public CountDownForm(int sec, string title, string richtext, StopCountDownCheck method)
        {
            InitializeComponent();
            _TimeOutSec = sec;
            _Method = method;
            this.Text = title;
            _MessageRTF = richtext;
            richTextBox1.Rtf = _MessageRTF;
            //_IsWindow = false;
        }

        /*
        /// <summary>
        /// Window Timeout Countdown Form : check if window name appear or not as Timeout Condition
        /// </summary>
        /// <param name="method">Things TO DO after Window Appear</param>
        /// <param name="sec">Time to start count down in second</param>
        /// <param name="Process">Process that contain the window</param>
        /// <param name="Window">Window Name to check if exist</param>
        public CountDownForm(int sec, DoNext donext, string Process, string Window, string richtext)
        {
            InitializeComponent();
            _Process = Process;
            _Window = Window;
            _TimeOutSec = sec;
            _DoNext = donext;
            this.Text = "WAIT FOR \"" + Window + "\" APPEAR";
            richTextBox1.Rtf = richtext;
            _IsWindow = true;
        }*/

        public object showdialog()
        {
            _CountDownSec = _TimeOutSec;
            _IsCounting = true;
            timer1.Start();
            // Block here & Wait
            _IsPolling = true;
            this.ShowDialog(); // This will not call Dispose until unblock show will call 1 more Timer Tick & cause double Form. Show Stop Timer first
            return _RetObj;
        }

        public bool IsCounting
        {
            get { return _IsCounting; }
            set { _IsCounting = value; }
        }

        /*
        /// <summary>
        /// Show the Timeout Countdown Form.
        /// </summary>
        /// <param name="polling">true : will block current thread & wait. false : will show form in another thread</param>
        public void show(bool polling)
        {
            _CountDownSec = _TimeOutSec;
            _IsCounting = true;
            timer1.Start();
            if (polling)
            {
                // Block here & Wait
                _IsPolling = true;
                this.ShowDialog(); // This will not call Dispose until unblock show will call 1 more Timer Tick & cause double Form. Show Stop Timer first
            }
            else
            {
                // New Thread
                _IsPolling = false;
                this.Show(); // This will call Dispose immediately so no need to Stop Timer. But either way ... Stop Timer before Form Close is good.
            }
        }*/

        private new void Close()
        {
            timer1.Stop(); // To avoid error when use .ShowDialog() will continue Timer Run until Unblock from ShowDialog & 'cause 1 more _Method call.
            base.Close();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            /*if (_IsWindow)
            {
                Process[] tmpProcs = Process.GetProcessesByName(_Process);
                foreach (Process proc in tmpProcs)
                {
                    if (proc.MainWindowTitle.Contains(_Window))
                    { // If Window appear
                        _DoNext(proc.MainWindowHandle);
                        this.Close();
                    }
                }
            }
            else*/
            {
                if (_Method(this, out _RetObj))
                { // Check Method Condition every 1 sec.
                    this.Close();
                }
            }

            if (!_IsCounting) return; // If stop counting then return, just check _Method Condition only

            if (_CountDownSec > 0) // Else Check CountDown
            {
                textBox1.Text = "Time Out in " + _CountDownSec.ToString() + " Seconds";
                _CountDownSec--;
                return;
            }
            // Timed Out
            _IsCounting = false;
            button1.Enabled = true; // Enable Continue Wait
            textBox1.Text = "Already Timed Out !";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            button1.Enabled = false;
            _CountDownSec = _TimeOutSec;
            _IsCounting = true;
            richTextBox1.Rtf = _MessageRTF;
            timer1.Start();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}
